//
// Normal.cpp for  in /home/herpec_j/Dropbox/Projets/raytracer-2016/Sources/Maths/
//
// Made by Jonathan
// Login   <ledey_l@epitech.net>
//
// Started on  Sun Sep 22 13:53:53 2013 Jonathan
// Last update Sun Sep 22 16:27:37 2013 Jonathan
//

#include		"Maths/Normal.hpp"
#include		"Maths/Vector.hpp"
#include		"Maths/Point.hpp"
#include		"Maths/Matrix.hpp"

namespace		Maths
{
  Normal::Normal(void) : mX(0.0f), mY(0.0f), mZ(0.0f)
  {
    return;
  }

  Normal::Normal(long double rValue) : mX(rValue), mY(rValue), mZ(rValue)
  {
    return;
  }

  Normal::Normal(long double rX, long double rY, long double rZ) : mX(rX), mY(rY), mZ(rZ)
  {
    return;
  }

  Normal::Normal(Normal const &rOther) : mX(rOther.mX), mY(rOther.mY), mZ(rOther.mZ)
  {
    return;
  }

  Normal::Normal(Vector const &rVector) : mX(rVector[0]), mY(rVector[1]), mZ(rVector[2])
  {
    return;
  }

  Normal::Normal(Point const &rPoint) : mX(rPoint[0]), mY(rPoint[1]), mZ(rPoint[2])
  {
    return;
  }

  Normal		&Normal::operator=(Normal const &rOther)
  {
    if (this != &rOther)
      {
	mX = rOther.mX;
	mY = rOther.mY;
	mZ = rOther.mZ;
      }
    return (*this);
  }

  Normal		&Normal::operator=(Vector const &rVector)
  {
    mX = rVector[0];
    mY = rVector[1];
    mZ = rVector[2];
    return (*this);
  }

  Normal		&Normal::operator=(Point const &rPoint)
  {
    mX = rPoint[0];
    mY = rPoint[1];
    mZ = rPoint[2];
    return (*this);
  }

  Normal		Normal::operator-(void) const
  {
    return (Normal(-mX, -mY, -mZ));
  }

  Normal		Normal::operator+(Normal const &rOther) const
  {
    return (Normal(mX + rOther.mX, mY + rOther.mY, mZ + rOther.mZ));
  }

  Normal		&Normal::operator+=(Normal const &rOther)
  {
    mX += rOther.mX;
    mY += rOther.mY;
    mZ += rOther.mZ;
    return (*this);
  }

  Normal		Normal::operator*(long double rValue) const
  {
    return (Normal(mX * rValue, mY * rValue, mZ * rValue));
  }

  long double		Normal::operator*(Vector const &rVector) const
  {
    return (mX * rVector[0] + mY * rVector[1] + mZ * rVector[2]);
  }

  long double		Normal::operator[](int rIndex) const
  {
    switch (rIndex)
      {
      case 0:
	return (mX);
	break;
      case 1:
	return (mY);
	break;
      case 2:
	return (mZ);
	break;
      default:
	return (0.0f);
	break;
      }
  }

  void			Normal::Normalize(void)
  {
    long double		length = sqrt(mX * mX + mY * mY + mZ * mZ);

    mX /= length;
    mY /= length;
    mZ /= length;
  }

  Normal::~Normal(void)
  {
    return;
  }

  Normal		operator*(long double rValue, Normal const &rNormal)
  {
    return (Normal(rValue * rNormal[0], rValue * rNormal[1], rValue * rNormal[2]));
  }

  Vector		operator+(Vector const &rVector, Normal const &rNormal)
  {
    return (Vector(rVector[0] + rNormal[0], rVector[1] + rNormal[1], rVector[2] + rNormal[2]));
  }

  Vector		operator-(Vector const &rVector, Normal const &rNormal)
  {
    return (Vector(rVector[0] - rNormal[0], rVector[1] - rNormal[1], rVector[2] - rNormal[2]));
  }

  long double		operator*(Vector const &rVector, Normal const &rNormal)
  {
    return (rVector[0] * rNormal[0] + rVector[1] * rNormal[1] + rVector[2] * rNormal[2]);
  }

  Normal		operator*(Matrix const &rMatrix, Normal const &rNormal)
  {
    long double		**matrix = rMatrix.GetMatrix();
    long double		x = rNormal[0];
    long double		y = rNormal[1];
    long double		z = rNormal[2];

    return (Normal(matrix[0][0] * x + matrix[1][0] * y + matrix[2][0] * z,
		   matrix[0][1] * x + matrix[1][1] * y + matrix[2][1] * z,
		   matrix[0][2] * x + matrix[1][2] * y + matrix[2][2] * z));
  }
};
